package pruebas.tiendaOl.general;

import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;

import org.jboss.weld.util.reflection.ParameterizedTypeImpl;

public class CdiTypeResolutionIssue {

	public interface BaseType<P> {}
	public interface DerivedType<T> extends BaseType<T> {}

	public interface SomeType1 {}
	public interface SomeType2 {}

	@Dependent
	public static class BeanClass1 implements DerivedType<SomeType1> {}
	@Dependent
	public static class BeanClass2 implements DerivedType<SomeType2> {}

	@ApplicationScoped
	public static class Test implements Serializable {
		@Inject
		private BaseType<SomeType1> field; // if not commented throws following exception during deployment: org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type [BaseType<SomeType1>] with qualifiers [@Default] at injection point [[field] @Inject private Test.field]. Possible dependencies [[Managed Bean [class BeanClass2] with qualifiers [@Any @Default], Managed Bean [class BeanClass1] with qualifiers [@Any @Default]]]

		@Inject
		private Instance<BaseType<SomeType1>> instance;
		@Inject
		private BeanManager bm;

		@PostConstruct
		private void postConstruct() {
			// This block outputs two bean classes:
			// beanClass: BeanClass1@11be5bab
			// beanClass: BeanClass2@764a72e9
			{
				Iterator<BaseType<SomeType1>> iterator = instance.iterator();
				while (iterator.hasNext()) {
					System.out.println("beanClass: " + iterator.next().toString());
				}
			}

			
			// And this block outputs:
			//
			// bean: Managed Bean [class BeanClass1] with qualifiers [@Any @Default]
			// beanTypes:
			//  - class BeanClass1
			//  - DerivedType<SomeType1>
			//  - class java.lang.Object
			//  - BaseType<T>
			//
			// bean: Managed Bean [class BeanClass2] with qualifiers [@Any @Default]
			// beanTypes:
			//  - DerivedType<SomeType2>
			//  - class java.lang.Object
			//  - class BeanClass2
			//  - BaseType<T>
			{
				Set<Bean<?>> beans = bm.getBeans(new ParameterizedTypeImpl(BaseType.class, new Type[] { SomeType1.class }, null));
				for (Bean<?> bean : beans) {
					System.out.println("\nbean: " + bean+"\nbeanTypes: ");
					for (Type beanType : bean.getTypes()) {
						System.out.println(" - " + beanType);
					}
				}

				bm.resolve(beans); // if not commeted throws an AmbiguousResolutionException
			}
		}
	}

}
